package com.lz.gmall.cart.service.impl;

import com.alibaba.fastjson.JSON;
import com.lz.gamll.feign.product.SkuDetailFeignClient;
import com.lz.gmall.cart.entity.CartItem;
import com.lz.gmall.cart.entity.SkuIdAndPrice;
import com.lz.gmall.cart.service.CartListService;
import com.lz.gmall.cart.vo.UserAuthInfoVo;
import com.lz.gmall.common.result.Result;
import com.lz.gmall.common.utils.UserAuthUtil;
import com.lz.gmall.constant.GmallConstant;
import com.lz.gmall.product.entity.SkuInfo;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;

import javax.annotation.PostConstruct;
import java.math.BigDecimal;
import java.util.List;
import java.util.Objects;
import java.util.Set;
import java.util.stream.Collectors;

@Service
public class CartListServiceImpl implements CartListService {

    @Autowired
    private RedisTemplate<String,String> redisTemplate;

    @Autowired
    private SkuDetailFeignClient skuDetailFeignClient;

//    @PostConstruct
//    public void init(){
//        List<SkuIdAndPrice> skuIdAndPrices = skuDetailFeignClient.getSkuAllPrice().getData();
//        for (SkuIdAndPrice skuIdAndPrice : skuIdAndPrices) {
//            Long skuId = skuIdAndPrice.getSkuId();
//            BigDecimal price = skuIdAndPrice.getPrice();
//            redisTemplate.opsForHash().put("sku:info:price",String.valueOf(skuId),String.valueOf(price));
//        }
//    }

    /**
     * 从mvc的工具类获取用户id或者用户临时id
     * 从redis中获取商品列表
     * @return
     */
    @Override
    public List<CartItem> getCartList() {

        UserAuthInfoVo userAuthInfo = UserAuthUtil.getUserAuthInfo();
        //断言，如果为 true，则程序将继续执行；如果为 false，则程序会抛出 AssertionError 异常，并输出一个断言失败的提示消息
        assert userAuthInfo != null;
        String userId = userAuthInfo.getUserId();
        String userTempId = userAuthInfo.getUserTempId();

        if (!StringUtils.isEmpty(userId) && !StringUtils.isEmpty(userTempId)){
            //有用户购物车和临时购物车，进行合并
            //临时购物车
            List<Object> userTempdCartObjList = redisTemplate.opsForHash().values(GmallConstant.REDIS_USER_CART_KEY + userTempId);
            //用户购物车
            List<Object> userCartObjList = redisTemplate.opsForHash().values(GmallConstant.REDIS_USER_CART_KEY + userId);
            //购物车合并
            userCartObjList.addAll(userTempdCartObjList);
            //去重
            Set<Long> longSet = userCartObjList.stream().map(obj -> {
                String cartItemJson = obj.toString();
                CartItem cartItem = JSON.parseObject(cartItemJson, CartItem.class);
                return cartItem.getId();
            }).collect(Collectors.toSet());

            if (longSet.size()>3){
                return getUserCartListAndNewPrice(userId);
            }

            //处理临时购物车
            List<CartItem> cartTempdItemList = userTempdCartObjList.stream().map(obj -> {
                String cartItemJson = obj.toString();
                return JSON.parseObject(cartItemJson, CartItem.class);
            }).collect(Collectors.toList());

            for (CartItem cartTempdItem : cartTempdItemList) {
                //判断用户购物车是否以及含有临时购物车商品
                Boolean hasKey = redisTemplate.opsForHash().hasKey(GmallConstant.REDIS_USER_CART_KEY + userId, String.valueOf(cartTempdItem.getSkuId()));
                if (hasKey){
                    //用户购物车以及含有临时购物车商品，进行数量相加
                    String cartItemJson = redisTemplate.opsForHash().get(GmallConstant.REDIS_USER_CART_KEY + userId, String.valueOf(cartTempdItem.getSkuId())).toString();
                    CartItem cartItem = JSON.parseObject(cartItemJson, CartItem.class);
                    cartItem.setSkuNum(cartItem.getSkuNum()+cartTempdItem.getSkuNum());
                    if (cartItem.getSkuNum()>10){
                        cartItem.setSkuNum(10);
                    }
                    redisTemplate.opsForHash().put(GmallConstant.REDIS_USER_CART_KEY + userId,String.valueOf(cartItem.getSkuId()),JSON.toJSONString(cartItem));
                }else {
                    //用户购物车以及不含有临时购物车商品，直接加入用户购物车
                    redisTemplate.opsForHash().put(GmallConstant.REDIS_USER_CART_KEY + userId, String.valueOf(cartTempdItem.getSkuId()),JSON.toJSONString(cartTempdItem));
                }
            }
            //合并完之后，删除临时购物车
            redisTemplate.delete(GmallConstant.REDIS_USER_CART_KEY+userTempId);

            //用户购物车
            return  getUserCartListAndNewPrice(userId);

        }else {
            //说明没有同时存在用户购物车和临时购物车，不需要进行合并
            String cartKey = getCartKey();

            List<Object> objectList = redisTemplate.opsForHash().values(cartKey);
            //对集合进行处理
            List<CartItem> cartItemList = objectList.stream().map(object -> {
                String cartItemString = object.toString();
                CartItem cartItem = JSON.parseObject(cartItemString, CartItem.class);
                //获取最新的价格
                //BigDecimal priceNew = new BigDecimal(redisTemplate.opsForHash().get("sku:info:price", String.valueOf(cartItem.getSkuId())).toString());
                updateCartItemPrice(cartItem,cartKey);
                //cartItem.setSkuPrice(priceNew);
                return cartItem;
            }).sorted((c1,c2)->{
                return (int)(c2.getCreateTime().getTime() - c1.getCreateTime().getTime());
            }).collect(Collectors.toList());

            return cartItemList;
        }
    }

    /**
     * 新的方案，每次点击购物车就重新查询数据库得到商品的最新价格，并且更新redis
     * @param cartItem
     * @param redisCartKey
     */
    private void updateCartItemPrice(CartItem cartItem , String redisCartKey) {
        //远程调用，访问数据库
        Result<SkuInfo> skuInfoResult = skuDetailFeignClient.getSkuInfoPriceBySkuId(cartItem.getSkuId());
        SkuInfo skuInfo = skuInfoResult.getData();
        cartItem.setSkuPrice(skuInfo.getPrice());
        // 更新Redis中的购物项价格
        redisTemplate.opsForHash().put(redisCartKey , String.valueOf(cartItem.getSkuId()) , JSON.toJSONString(cartItem));

    }

    /**
     * 获取最新价格的合并之后的用户购物车商品列表
     * @param userId
     * @return
     */
    private List<CartItem> getUserCartListAndNewPrice(String userId) {

        List<Object> userCartList = redisTemplate.opsForHash().values(GmallConstant.REDIS_USER_CART_KEY + userId);
        return userCartList.stream().map(obj->{
            String json = obj.toString();
            CartItem cartItem = JSON.parseObject(json, CartItem.class);
            //BigDecimal priceNew = new BigDecimal(redisTemplate.opsForHash().get("sku:info:price", String.valueOf(cartItem.getSkuId())).toString());
            updateCartItemPrice(cartItem , GmallConstant.REDIS_USER_CART_KEY + userId);
            //cartItem.setSkuPrice(priceNew);
            return cartItem;
        }).sorted((c1,c2)->{
            return (int)(c2.getCreateTime().getTime() - c1.getCreateTime().getTime());
        }).collect(Collectors.toList());
    }

    /**
     * 对redis中的商品数量进行修改
     * @param skuId 商品id
     * @param skuNum 进行加一或者减一
     */
    @Override
    public void updateCartSkuNum(Long skuId, Integer skuNum) {
        String cartKey = getCartKey();
        String cartItemJson = Objects.requireNonNull(redisTemplate.opsForHash().get(cartKey, String.valueOf(skuId))).toString();
        CartItem cartItem = JSON.parseObject(cartItemJson, CartItem.class);

        cartItem.setSkuNum(Math.min(cartItem.getSkuNum() + skuNum, 10));

        redisTemplate.opsForHash().put(cartKey,String.valueOf(skuId),JSON.toJSONString(cartItem));
    }

    /**
     * 修改购物车中商品的选中状态
     * @param skuId 商品id
     * @param isChecked 修改商品的选中状态
     */
    @Override
    public void updateCartCheck(Long skuId, Integer isChecked) {
        String cartKey = getCartKey();
        String cartItemJson = Objects.requireNonNull(redisTemplate.opsForHash().get(cartKey, String.valueOf(skuId))).toString();
        CartItem cartItem = JSON.parseObject(cartItemJson, CartItem.class);
        cartItem.setIsChecked(isChecked);

        redisTemplate.opsForHash().put(cartKey,String.valueOf(skuId),JSON.toJSONString(cartItem));
    }

    /**
     * 根据商品id删除购物车redis中的商品
     * @param skuId 商品id
     */
    @Override
    public void deleteCartSkuBySkuId(Long skuId) {
        String cartKey = getCartKey();
        redisTemplate.opsForHash().delete(cartKey,String.valueOf(skuId));
    }

    /**
     * 查询redis购物车中的商品的选中状态，选中状态下的商品批量删除
     */
    @Override
    public void deleteCartSkusByChecked() {
        String cartKey = getCartKey();

        List<CartItem> cartItemList = getCartList();

        cartItemList.forEach(cartItem -> {
            if (cartItem.getIsChecked()==1){
                redisTemplate.opsForHash().delete(cartKey,String.valueOf(cartItem.getSkuId()));
            }
        });
    }

    private String getCartKey() {
        //获取请求头中的用户id和临时id
        UserAuthInfoVo userAuthInfo = UserAuthUtil.getUserAuthInfo();
        String userId = userAuthInfo.getUserId();
        String userTempId = userAuthInfo.getUserTempId();

        if (!StringUtils.isEmpty(userId)){
            //说明用户已经登录了
            return GmallConstant.REDIS_USER_CART_KEY + userId;
        }else {
            //说明用户没有登录
            return GmallConstant.REDIS_USER_CART_KEY+userTempId;
        }
    }
}
